package com.ssm.basis.web.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import java.util.Collections;

import static com.ssm.basis.service.constant.SecurityConstant.HEADER_X_AUTH_TOKEN;
import static io.swagger.v3.oas.models.security.SecurityScheme.In.HEADER;
import static io.swagger.v3.oas.models.security.SecurityScheme.Type.APIKEY;
import static io.swagger.v3.oas.models.security.SecurityScheme.Type.HTTP;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;

/**
 * https://editor.swagger.io
 * https://swagger.io/specification
 */
@Slf4j
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true)
class SwaggerConfig {
    /**
     * @see OpenApiCustomiser
     * https://blog.csdn.net/m0_47333020/article/details/109776819
     */
    @Bean
    OpenAPI ssmOpenAPI() {
        Components components = new Components();
        SecurityScheme basic = new SecurityScheme().type(HTTP).scheme("basic");
        components.addSecuritySchemes("basicScheme", basic);
        SecurityScheme xat = new SecurityScheme().type(APIKEY).name(HEADER_X_AUTH_TOKEN).in(HEADER);
        components.addSecuritySchemes("xatScheme", xat);
        SecurityScheme token = new SecurityScheme().type(APIKEY).name(AUTHORIZATION).in(HEADER);
        components.addSecuritySchemes("tokenScheme", token);
        SecurityScheme jwt = new SecurityScheme().type(HTTP).scheme("bearer").bearerFormat("JWT");
        components.addSecuritySchemes("jwtScheme", jwt);

        SecurityRequirement securityRequirement = new SecurityRequirement();
        securityRequirement.addList("basicScheme");
        securityRequirement.addList("xatScheme");
        securityRequirement.addList("tokenScheme");
        securityRequirement.addList("jwtScheme");

        return new OpenAPI()
                .components(components)
                .security(Collections.singletonList(securityRequirement))
                .info(new Info().title("SSM API")
                        .description("ssm sample application")
                        .version("v0.0.1")
                        .license(new License().name("Apache 2.0").url("http://springdoc.org"))
                ).externalDocs(new ExternalDocumentation()
                        .description("Spring Boot Version: " + SpringBootVersion.getVersion())
                        .url("https://spring.io/projects/spring-boot#learn")
                );
    }

    // @LocalServerPort
    // private String port;

    @Bean
    @Profile("dev")
    ApplicationListener<ApplicationReadyEvent> swaggerUrlPrint() {
        // 事件机制：https://blog.csdn.net/f641385712/article/details/88806639
        return event -> {
            String port = event.getApplicationContext().getEnvironment().getProperty("local.server.port");
            log.info("{}：http://127.0.0.1:{}/swagger-ui.html", "Swagger UI", port);
        };
    }
}
